/*
 * Licensed to the 南京汇海交通科技有限公司
 *
 * Copyright (c) 2025.
 * All rights reserved.
 *
 * 本软件属南京汇海交通科技有限公司所有，在未获得南京汇海交通科技有限公司正式授权情况下，任何企业和个人，不能获取、阅读、安装、传播本软件涉及的任何受知识产权保护的内容。
 */
package com.chframework.cloud.web.advice.basic;

import cn.hutool.json.JSONUtil;
import com.chframework.common.extend.AspectHelper;
import lombok.extern.slf4j.Slf4j;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

import java.util.StringJoiner;

/**
 * 自定义拦截器
 */
@Slf4j
public class ServiceMethodInterceptor implements MethodInterceptor {

    @Override
    public Object invoke(MethodInvocation methodInvocation) throws Throwable {
        Object result;
        long startTime = System.currentTimeMillis();
        Object source = methodInvocation.getThis(); // 被代理的类实例对象
        String packagePathName = source.getClass().getTypeName(); // 被代理的类完整限定名，包括泛型
        String methodName = methodInvocation.getMethod().getName(); // 被代理的方法名称
        try {
            // 前置通知
            // something will be done.
            Object[] args = methodInvocation.getArguments(); // 代理的方法参数列表
            // 特别注意：
            // （1）假如微服务的web框架是基于Servlet服务构建的，执行这个方法
            StringJoiner joiner = AspectHelper.requestParamJoiner(packagePathName, methodName, args);
            // （2）假如微服务的web框架是基于Reactive响应式服务构建的，执行这个方法
            // StringJoiner joiner = ReactiveAspectHelper.requestParamJoiner(packagePathName, methodName, args);
            // （3）此处若要改造，请参考 {@link com.chframework.boot.web.advice.HttpAspect} 的做法。
            if (joiner.length() > 0) {
                log.info(joiner.toString());
            }

            result =  methodInvocation.proceed();

            // 后置通知
            // something will be done.
            if (joiner.length() > 0) {
                log.debug("请求结束");
                String jsonResultValue = result == null ? null : JSONUtil.toJsonStr(result);
                log.info("返回结果response={}", jsonResultValue);
            }
        } catch (Throwable throwable) {
            // 异常通知
            // something will be done.
            log.error("执行 {}.{} 时发生异常", packagePathName, methodName, throwable);
            throw throwable;
        } finally {
            // 返回通知
            // something will be done.
            log.info("执行 {}.{} 共耗时 {} 毫秒", packagePathName, methodName, System.currentTimeMillis() - startTime);
        }

        return result;
    }
}
